﻿/**
 *
 *	A basic interactive object. Makes it easier to add a custom implementation for the things like enabling/disabling, custom mouse up and mouse down animations etc.
 *	It operates only with the states DynamicState.UP and DynamicState.DOWN.
 *
 *	@author	Valentyn Derkach
 *
 *	2008.05.07
 *	Changes:
 *	 -	constants STATE_UP and STATE_DN has been removed for the sake of using the DynamicState class.
 *
 *	2008.06.15
 *	Changes:
 *	 -	methods doEnable, doDisable has been added
 *
 * 
 */


package com.bizmlib.ui.display
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.display.MovieClip;
	import com.bizmlib.ui.display.MouseEventExtended;
	
	
	public class ClickableMovie extends MovieClip
	{
		/**
		 * A state variable reflects the state of the instance.
		 */
		protected var __state:String;
		protected var ignoreMouseEnabledForMouseDown:Boolean = true;
		protected var ignoreMouseEnabledForMouseUp:Boolean = true;
		
		
		public function ClickableMovie()
		{
			init();
		}
		
		
		public function get state():String
		{
			return __state;
		}
		
		
		override public function set mouseEnabled(value:Boolean):void
		{
			if(value==super.mouseEnabled)
			{
				return;
			}
			
			super.mouseEnabled = value;
			
			afterMouseEnabledUpdate();
		}
		override public function get mouseEnabled():Boolean
		{
			return super.mouseEnabled;
		}
		protected function afterMouseEnabledUpdate():Boolean
		{
			if(mouseEnabled)
			{
				doEnable();
			}
			else
			{
				doDisable();
			}
			
			if(!mouseEnabled && state==DynamicState.DOWN)
			{
				releaseImplementation();
				return true;
			}
			
			return false;
		}
		
		
		public function release():void
		{
			releaseImplementation();
		}
		public function clean():void
		{
			this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
		}
		
		
		protected function init():void
		{
			__state = DynamicState.UP;
			
			this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			this.addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
			
			afterInit();
		}
		protected function afterInit():void
		{
		}
		
		
		protected function mouseDown(event:MouseEvent):void
		{
			//trace(this + ".mouseDown(" + arguments + ")");
			
			if(!ignoreMouseEnabledForMouseDown && !mouseEnabled)
			{
				return;
			}
			
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
			
			__state = DynamicState.DOWN;
			
			doMouseDown();
		}
		protected function mouseUp(event:MouseEvent):void
		{
			//trace(this + ".mouseUp(" + arguments + ")");
			
			if(!ignoreMouseEnabledForMouseUp && !mouseEnabled)
			{
				return;
			}
			
			releaseImplementation();
			
			dispatchEvent(MouseEventExtended.createFromSource(event, MouseEventExtended.MOUSE_RELEASE));
		}
		protected function releaseImplementation(doStateChange:Boolean = true, invokeCustomImplementation:Boolean = true):void
		{
			//trace(this + ".release(" + arguments + ")");
			
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
			
			if(doStateChange)
			{
				__state = DynamicState.UP;
			}
			
			if(invokeCustomImplementation)
			{
				doMouseUp();
			}
		}
		
		
		protected function doMouseDown():void
		{
			//trace(this + ".doMouseDown(" + arguments + ")");
		}
		protected function doMouseUp():void
		{
			//trace(this + ".doMouseUp(" + arguments + ")");
		}
		/**
		 * Invoked when the mouseEnabled property turns to 'true'. Override this method in order to put your own actions, which has to be invoked in that case.
		 * Note that mouseEnabled property equals 'true' by default and doEnable is not invoked when the class is instantiated. It only handles the later changes.
		 * This method is invoked from an afterMouseEnabledUpdate, so be careful when overriding the last one.
		 */
		protected function doEnable():void
		{
		}
		/**
		 * Invoked when the mouseEnabled property turns to 'false'. Override this method in order to put your own actions, which has to be invoked in that case.
		 * This method is invoked from an afterMouseEnabledUpdate, so be careful when overriding the last one.
		 */
		protected function doDisable():void
		{
		}
		/**
		 * is not currently in use
		 */
		protected function doMouseMove():void
		{
			//trace(this + ".doMouseMove(" + arguments + ")");
		}
		
		
		private function removedFromStage(event:Event):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
		}
		
		override public function toString():String
		{
			return "[com.bizmlib.ui.display.ClickableMovie]";
		}
	}
}